"""
密码保护页面处理器

专门处理密码保护页面的识别、密码提取和输入操作
"""

import asyncio
import sys
import re
from typing import Dict, Any, Optional
from playwright.async_api import Page
from pathlib import Path

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))

try:
    from src.browser.page_handler import BasePageHandler
    from src.utils.logger import get_logger
    from src.exceptions.exceptions import PageElementException
except ImportError:
    try:
        from browser.page_handler import BasePageHandler
        from utils.logger import get_logger
        from exceptions.exceptions import PageElementException
    except ImportError:
        from page_handler import BasePageHandler
        from logger import get_logger
        from exceptions import PageElementException

logger = get_logger(__name__)


class PasswordProtectedPageHandler(BasePageHandler):
    """密码保护页面处理器类"""
    
    def __init__(self, page: Page):
        super().__init__(page)
        
        # 密码保护页面的识别选择器
        self.password_protection_selectors = [
            'h1:has-text("密码保护")',
            'h1.entry-title:has-text("密码保护")',
            '.entry-title:has-text("密码保护")',
            '*:has-text("密码保护")',
            'h1[class*="title"]:has-text("密码保护")',
            'h2:has-text("密码保护")',
            'h3:has-text("密码保护")'
        ]
        
        # 密码输入框选择器
        self.password_input_selectors = [
            'input[name="post_password"]',
            '#pwbox-30110',
            'input[type="password"]',
            'input[id*="pwbox"]',
            'input[name*="password"]'
        ]
        
        # 提交按钮选择器
        self.submit_button_selectors = [
            'input[type="submit"][name="Submit"]',
            '#post-30110 > div:nth-child(2) > div > div.entry-content.u-text-format.u-clearfix > form > p:nth-child(2) > input[type=submit]',
            'input[type="submit"]',
            'button[type="submit"]',
            'input[value="提交"]',
            'button:has-text("提交")'
        ]
    
    async def handle(self) -> Dict[str, Any]:
        """
        处理密码保护页面
        
        Returns:
            Dict: 处理结果
        """
        try:
            # 等待页面加载
            await self.wait_for_page_load()
            
            # 检查是否为密码保护页面
            is_password_page = await self.is_password_protected_page()
            if not is_password_page:
                return {
                    "success": False,
                    "error": "当前页面不是密码保护页面",
                    "page_type": "unknown"
                }
            
            self.logger.info("✅ 检测到密码保护页面")
            
            # 提取密码
            password = await self.extract_password()
            if not password:
                return {
                    "success": False,
                    "error": "无法提取密码信息",
                    "page_type": "password_protected"
                }
            
            self.logger.info(f"🔑 成功提取密码: {password}")
            
            # 输入密码并提交
            submit_result = await self.input_password_and_submit(password)
            if not submit_result:
                return {
                    "success": False,
                    "error": "密码输入或提交失败",
                    "page_type": "password_protected",
                    "extracted_password": password
                }
            
            # 等待页面跳转
            await self.wait_for_page_redirect()
            
            return {
                "success": True,
                "message": "密码保护页面处理完成",
                "page_type": "password_protected",
                "extracted_password": password,
                "action_taken": "password_submitted"
            }
            
        except Exception as e:
            self.logger.error(f"处理密码保护页面时出错: {str(e)}")
            return {
                "success": False,
                "error": f"处理失败: {str(e)}",
                "page_type": "password_protected"
            }
    
    async def is_password_protected_page(self) -> bool:
        """
        检查当前页面是否为密码保护页面
        
        Returns:
            bool: 是否为密码保护页面
        """
        try:
            # 检查页面中是否包含"密码保护"文字
            for selector in self.password_protection_selectors:
                try:
                    element = await self.page.wait_for_selector(selector, timeout=3000)
                    if element:
                        text_content = await element.text_content()
                        if text_content and "密码保护" in text_content:
                            self.logger.info(f"通过选择器 {selector} 检测到密码保护页面")
                            return True
                except Exception:
                    continue
            
            # 备用检测方法：检查页面文本内容
            page_content = await self.page.content()
            if "密码保护" in page_content:
                self.logger.info("通过页面内容检测到密码保护页面")
                return True
            
            return False
            
        except Exception as e:
            self.logger.error(f"检测密码保护页面时出错: {str(e)}")
            return False
    
    async def extract_password(self) -> Optional[str]:
        """
        从页面中提取密码信息
        
        Returns:
            str: 提取的密码，如果提取失败则返回None
        """
        try:
            # 查找包含密码保护信息的元素
            password_elements = []
            
            # 尝试多种选择器查找密码元素
            selectors_to_try = [
                'h1.entry-title',
                'h1:has-text("密码保护")',
                '.entry-title:has-text("密码保护")',
                'h1',
                'h2',
                'h3',
                '*:has-text("密码保护")'
            ]
            
            for selector in selectors_to_try:
                try:
                    elements = await self.page.query_selector_all(selector)
                    for element in elements:
                        text_content = await element.text_content()
                        if text_content and "密码保护" in text_content:
                            password_elements.append((element, text_content))
                except Exception:
                    continue
            
            # 从找到的元素中提取密码
            for element, text_content in password_elements:
                password = self._extract_password_from_text(text_content)
                if password:
                    self.logger.info(f"从文本 '{text_content}' 中提取到密码: {password}")
                    return password
            
            # 如果上述方法都失败，尝试从页面内容中直接搜索
            page_content = await self.page.content()
            password = self._extract_password_from_text(page_content)
            if password:
                self.logger.info(f"从页面内容中提取到密码: {password}")
                return password
            
            self.logger.warning("未能从页面中提取到密码信息")
            return None
            
        except Exception as e:
            self.logger.error(f"提取密码时出错: {str(e)}")
            return None
    
    def _extract_password_from_text(self, text: str) -> Optional[str]:
        """
        从文本中提取密码
        
        Args:
            text: 包含密码信息的文本
            
        Returns:
            str: 提取的密码
        """
        if not text:
            return None
        
        # 定义密码提取的正则表达式模式
        patterns = [
            r'密码保护：([A-Za-z0-9]+)',  # 密码保护：A01173
            r'密码保护:\s*([A-Za-z0-9]+)',  # 密码保护: 52263
            r'密码保护\s*[:：]\s*([A-Za-z0-9]+)',  # 密码保护 : abc123
            r'密码保护\s+([A-Za-z0-9]+)',  # 密码保护 test123
            r'密码保护.*?([A-Za-z0-9]{3,})',  # 密码保护...xyz789 (至少3个字符)
        ]
        
        for pattern in patterns:
            match = re.search(pattern, text)
            if match:
                password = match.group(1).strip()
                if password:
                    return password
        
        return None
    
    async def input_password_and_submit(self, password: str) -> bool:
        """
        输入密码并提交
        
        Args:
            password: 要输入的密码
            
        Returns:
            bool: 是否成功输入并提交
        """
        try:
            # 查找密码输入框
            password_input = None
            for selector in self.password_input_selectors:
                try:
                    password_input = await self.page.wait_for_selector(selector, timeout=5000)
                    if password_input:
                        self.logger.info(f"找到密码输入框: {selector}")
                        break
                except Exception:
                    continue
            
            if not password_input:
                self.logger.error("未找到密码输入框")
                return False
            
            # 确保元素可见并滚动到视图中
            try:
                await password_input.scroll_into_view_if_needed()
                await asyncio.sleep(0.5)
                
                # 等待元素变为可见和可编辑
                await password_input.wait_for_element_state("visible", timeout=10000)
                await password_input.wait_for_element_state("editable", timeout=10000)
                
                self.logger.info("密码输入框已可见且可编辑")
            except Exception as e:
                self.logger.warning(f"等待密码输入框可见时出错: {str(e)}")
                # 继续尝试，可能元素实际上是可用的
            
            # 尝试点击输入框以确保焦点
            try:
                await password_input.click()
                await asyncio.sleep(0.3)
            except Exception as e:
                self.logger.warning(f"点击密码输入框时出错: {str(e)}")
            
            # 清空输入框并输入密码
            try:
                await password_input.clear()
                await asyncio.sleep(0.2)
                await password_input.fill(password)
                self.logger.info(f"✅ 成功输入密码: {password}")
            except Exception as e:
                # 如果fill失败，尝试使用type方法
                self.logger.warning(f"fill方法失败，尝试type方法: {str(e)}")
                try:
                    await password_input.click()
                    await password_input.press("Control+a")  # 全选
                    await password_input.type(password)
                    self.logger.info(f"✅ 使用type方法成功输入密码: {password}")
                except Exception as e2:
                    self.logger.error(f"type方法也失败: {str(e2)}")
                    return False
            
            # 等待一下确保输入完成
            await asyncio.sleep(0.5)
            
            # 查找并点击提交按钮
            submit_button = None
            for selector in self.submit_button_selectors:
                try:
                    submit_button = await self.page.wait_for_selector(selector, timeout=5000)
                    if submit_button:
                        self.logger.info(f"找到提交按钮: {selector}")
                        break
                except Exception:
                    continue
            
            if not submit_button:
                self.logger.error("未找到提交按钮")
                # 尝试按回车键提交
                try:
                    await password_input.press("Enter")
                    self.logger.info("✅ 使用回车键提交密码")
                    return True
                except Exception as e:
                    self.logger.error(f"回车键提交失败: {str(e)}")
                    return False
            
            # 确保提交按钮可见并点击
            try:
                await submit_button.scroll_into_view_if_needed()
                await asyncio.sleep(0.3)
                await submit_button.click()
                self.logger.info("✅ 成功点击提交按钮")
            except Exception as e:
                self.logger.error(f"点击提交按钮失败: {str(e)}")
                return False
            
            return True
            
        except Exception as e:
            self.logger.error(f"输入密码并提交时出错: {str(e)}")
            return False
    
    async def wait_for_page_redirect(self, timeout: int = 10000) -> bool:
        """
        等待页面跳转完成
        
        Args:
            timeout: 超时时间（毫秒）
            
        Returns:
            bool: 是否成功跳转
        """
        try:
            # 记录当前URL
            current_url = self.page.url
            self.logger.info(f"等待页面跳转，当前URL: {current_url}")
            
            # 等待页面跳转或加载完成
            await self.page.wait_for_load_state("networkidle", timeout=timeout)
            
            # 检查URL是否发生变化
            new_url = self.page.url
            if new_url != current_url:
                self.logger.info(f"✅ 页面已跳转到: {new_url}")
            else:
                self.logger.info("页面未跳转，但加载已完成")
            
            return True
            
        except Exception as e:
            self.logger.warning(f"等待页面跳转时出错: {str(e)}")
            return False
    
    async def get_page_info(self) -> Dict[str, Any]:
        """
        获取当前页面信息
        
        Returns:
            Dict: 页面信息
        """
        try:
            return {
                "url": self.page.url,
                "title": await self.page.title(),
                "is_password_protected": await self.is_password_protected_page(),
                "has_password_input": await self._has_password_input(),
                "has_submit_button": await self._has_submit_button()
            }
        except Exception as e:
            self.logger.error(f"获取页面信息时出错: {str(e)}")
            return {"error": str(e)}
    
    async def _has_password_input(self) -> bool:
        """检查页面是否有密码输入框"""
        for selector in self.password_input_selectors:
            try:
                element = await self.page.query_selector(selector)
                if element:
                    return True
            except Exception:
                continue
        return False
    
    async def _has_submit_button(self) -> bool:
        """检查页面是否有提交按钮"""
        for selector in self.submit_button_selectors:
            try:
                element = await self.page.query_selector(selector)
                if element:
                    return True
            except Exception:
                continue
        return False